---
slug:  definedProperty #路径，不能重复
title:  Object.defineProperty # 标题
authors: [] # 作者，在authors.yml配置
tags: [facebook, hello, docusaurus] # 标签，在tags.yml配置
toc_min_heading_level: 2 # 最小展示标题
toc_max_heading_level: 5 # 最大展示标题
---

### 查看对象成员的规则

#### `Object.getOwnPropertyDescriptors(对象)`
> 获取对象的所有成员的规则

```js
const obj = {x:1};
console.log(Object.getOwnPropertyDescriptors(obj));
```

```shell
{
    "x": {
        "value": 1,
        "writable": true,
        "enumerable": true,
        "configurable": true
    }
}
```
---

#### `Object.getOwnPropertyDescriptor(对象,成员)`
> 获取对象某个成员的规则

```js
const obj = {x:1}
console.log(Object.getOwnPropertyDescriptor(obj,'x'));
```

```shell
{
    "value": 1,
    "writable": true,
    "enumerable": true,
    "configurable": true
}
```

#### 规则
1. `configurable` 是否可以删除
2. `writable` 是否可以更改
3. `enumerable` 是否可以被枚举,可以被`for in`或者`Object.keys`列举出来的属性是可以枚举的
4. `value` 成员值

---

### `Object.defineProperty`
> 为一个对象定义规则

`Object.defineProperty(对象,成员,{规则})`

#### 拦截器
> 在`Object.defineProperty()`的规则的get和set是拦截器

```js
const obj = {x:1};

Object.defineProperty(obj,x,{
    get(){
        //读取成员值x的时候触发:obj.x
    },
    set(val){
        //修改成员值x时候触发,val是设置的值: obj.x = 1
    }
})
```


### 装饰器
:::warning
vs-code 不支持类的装饰器，需要开启
:::


:::warning
`create-react-app`也不支持类的装饰器
:::

```shell title="运行命令"
npm install @babel/core @babel/plugin-proposal-decorators @babel/preset-env @babel/plugin-proposal-class-properties

```

```json title="修改package.json"
{
"babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      ["@babel/plugin-proposal-decorators", { "legacy": true }],
      ["@babel/plugin-proposal-class-properties", { "loose": false }],
      ["@babel/plugin-transform-private-methods", { "loose": false }],
      ["@babel/plugin-transform-private-property-in-object", { "loose": false }]
    ]
  }
}

```

#### 解释

```js
" @babel/plugin-proposal-decorators"//支持装饰器语法
{
    "legacy": true//以遗留版本为主
}

[
        "@babel/plugin-proposal-class-properties",//编译class的插件
        {
          "loose": false//false通过Object.defineProperty设置,true直接设置
        }
      ]
```


#### 装饰器解释

##### 类的装饰器
> 类装饰器在类声明之前声明，可以用来监视,修改或替换类的定义


```js
const test = clazz=>{
    //拿到的就是NumClazz
    clazz.num = 100;

    //返回什么NumClazz调用时候就返回什么，什么都不返回的话NumClazz调用返回类
    return clazz.num;
}

@test
class NumClazz{}

console.log(NumClazz());//=> 100

```

##### 属性装饰器
> 定义在属性上
1. `target` 属性所属的类`.prototype`
2. `name` 属性名
3. `descriptor` 规则描述符
    * `initializer` 是个**函数**,调用返回初始值

```js
const test = (target,name,descriptor)=>{
        console.log(target,'target');
        console.log(descriptor,'descriptor');
        console.log(name,'name');
    }


    class Demo{

        @test
        num=1
    }
```
---
输出:

```shell
{} target

{
    "configurable": true,
    "enumerable": true,
    "initializer":()
    "writable": true
} descriptor

num name
```